﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace CC.Common
{
    
    public class DataTableHelper
    {
        
        /// <summary>
        /// 将DataTable转化为XML输出
        /// </summary>
        /// <param name="dataTable">DataTable</param>
        /// <param name="fileName">文件名称</param>
        public static void DataTableToXML(DataTable dataTable, string fileName)
        {
           
            using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
            {
                using (XmlWriter xmlWriter = XmlWriter.Create(fs))
                {
                    dataTable.WriteXml(xmlWriter, XmlWriteMode.IgnoreSchema);
                }
            }

        }
        /// <summary>
        /// 把实体清单转换为数据表
        /// 如果类里面用DataColumnAttribute设置了ColumnIgnore,则忽略
        /// 如果类里面用DataColumnAttribute设置了ColumnName，则使用ColumnName
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable IEnumerableToDataTable<T>(IEnumerable<T>list)
        {
            var type = typeof(T);
            DataTable table = new DataTable();
            var props = type.GetProperties().Where(p => !DataColumnAttribute.IsColumnIgnore(p)&&!DataColumnAttribute.IsAutoIncrement(p)).ToList();
           
            foreach (var prop in props)
            {
                string colName = DataColumnAttribute.GetColumnName(prop);
                if (string.IsNullOrEmpty(colName))
                {
                    colName = prop.Name;
                }
                table.Columns.Add(colName);
            }
            foreach (var item in list)
            {
                DataRow row = table.NewRow();
                foreach (DataColumn column in table.Columns)
                {
                    
                    for (int i = 0; i < table.Columns.Count; ++i)
                        row[i] = props[i].GetValue(item,null);
                }
                table.Rows.Add(row);
            }
            return table;
        }
        /// <summary>
        /// DataTable转换成List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <returns></returns>
        public static List<T>DataTableToList<T>(DataTable table)
        {//因不能保证属性与table的列之间有顺序对应关系，需要用列名来索引数值
            var type = typeof(T);
            List<T> list = new List<T>();
            var props = type.GetProperties().Where(p => !DataColumnAttribute.IsColumnIgnore(p)).ToList();
            Dictionary<string, string> propNameColNames = new Dictionary<string, string>();
            
            //用一个字典暂存属性名和列名的关系，在设置行值时要用
            foreach (var prop in props)
            {
                string colName = DataColumnAttribute.GetColumnName(prop);
                if (!string.IsNullOrEmpty(colName))
                {
                    propNameColNames.Add(prop.Name, colName);
                }
            }
            foreach (DataRow row in table.Rows)
            {
                T obj = System.Activator.CreateInstance<T>();
                foreach (var prop in props)
                {
                    var cName = propNameColNames.ContainsKey(prop.Name) ? propNameColNames[prop.Name] : prop.Name;
                    object value = row[cName] == DBNull.Value ? null : row[cName];
                    prop.SetValue(obj, value,null);
                }
               
                list.Add(obj);
            }
            return list;
        }

        /// <summary>
        /// 为table添加最大、最小、平均、范围行
        /// </summary>
        /// <param name="table">要操作的数据表。注意第一列为标题列，必须为字符串型</param>
        /// <param name="skipSummaryColumns">是否跳过汇总列</param>
        public static  void EvalRowSummary(DataTable table,bool skipSummaryColumns=false)
        {
            if(!HasSummaryRow(table))
            {
                var rowMin = table.Rows.Add("Min");
                var rowMax = table.Rows.Add("Max");
                var rowAvg = table.Rows.Add("Average");
                var rowRange = table.Rows.Add("Range");
                int endColNum = skipSummaryColumns && HasSummaryColumn(table) ? table.Columns.Count - 4 : table.Columns.Count - 1;
                for (int i = 1; i <= endColNum; i++)
                {
                    List<float> values = new List<float>();
                    foreach (DataRow row in table.Rows)
                    {
                        if (row[i] != DBNull.Value)
                            values.Add(Convert.ToSingle(row[i]));
                    }
                    float max = values.Max();
                    float min = values.Min();
                    rowMin[i] = min;
                    rowMax[i] = max;
                    rowAvg[i] = values.Average();
                    rowRange[i] = max - min;
                }
            }
           
        }
        /// <summary>
        /// 为table添加最大、最小、平均、范围列
        /// </summary>
        /// <param name="table">要操作的数据表。注意第一列为标题列，必须为字符串型</param>
        /// <param name="skipSummaryRows">是否跳过汇总行</param>
        public static void EvalColumnSummary(DataTable table, bool skipSummaryRows = false)
        {
            if (!HasSummaryColumn(table))
            {
                table.Columns.Add("Min");
                table.Columns.Add("Max");
                table.Columns.Add("Average");
                table.Columns.Add("Range");
                int endRowNum = skipSummaryRows && HasSummaryRow(table) ? table.Rows.Count - 4 : table.Rows.Count - 1;
                for (int i = 0; i <= endRowNum; i++)
                {
                    var row = table.Rows[i];
                    List<float> values = new List<float>();
                    foreach (var item in row.ItemArray)
                    {
                        if (item != DBNull.Value)
                            values.Add(Convert.ToSingle(item));
                    }
                    float max = values.Max();
                    float min = values.Min();
                    row["Min"] = min;
                    row["Max"] = max;
                    row["Average"] = values.Average();
                    row["Range"] = max - min;
                }
            }

        }
        /// <summary>
        /// 如果给定的数据表含有汇总行，则删除汇总行
        /// </summary>
        /// <param name="table"></param>
        public void RemoveSummaryColumns(DataTable table)
        {
            if (HasSummaryColumn(table))
            {
                table.Columns.RemoveAt(table.Columns.Count - 1);
                table.Columns.RemoveAt(table.Columns.Count - 1);
                table.Columns.RemoveAt(table.Columns.Count - 1);
                table.Columns.RemoveAt(table.Columns.Count - 1);
            }

        }
        /// <summary>
        /// 如果给定的数据表含有汇总行，则删除汇总行
        /// </summary>
        /// <param name="table"></param>
        public void RemoveSummaryRows(DataTable table)
        {
            if(HasSummaryRow(table))
            {
                table.Rows.RemoveAt(table.Rows.Count - 1);
                table.Rows.RemoveAt(table.Rows.Count - 1);
                table.Rows.RemoveAt(table.Rows.Count - 1);
                table.Rows.RemoveAt(table.Rows.Count - 1);
            }
            
        }
        /// <summary>
        /// 判断是否含有汇总列（以是否含有Max列名为标准）
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private static bool HasSummaryColumn(DataTable table)
        {
            bool has = false;
            foreach (DataColumn column in table.Columns)
            {
                if (string.Compare(column.ColumnName, "Max", true) == 0)
                {
                    has = true;
                    break;
                }
            }
            return has;
        }
        /// <summary>
        /// 判断是否含有汇总列（以是否含有Max行标题为标准）
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private static bool HasSummaryRow(DataTable table)
        {
            bool has = false;
            foreach (DataRow    row in table.Rows)
            {
                if(row[0]!=DBNull.Value)
                {
                    if (string.Compare(row[0].ToString(), "Max", true) == 0)
                    {
                        has = true;
                        break;
                    }
                }
                
            }
            return has;
        }
    }
}
